Skip to content

[Windows] TabbedPage: Refresh layout when NavigationView size changes#26217

Merged
kubaflo merged 9 commits intodotnet:inflight/currentfrom
BagavathiPerumal:fix-26103
Apr 13, 2026
Merged

[Windows] TabbedPage: Refresh layout when NavigationView size changes#26217
kubaflo merged 9 commits intodotnet:inflight/currentfrom
BagavathiPerumal:fix-26103

Conversation

@BagavathiPerumal
Copy link
Copy Markdown
Contributor

@BagavathiPerumal BagavathiPerumal commented Nov 29, 2024

Root cause

The issue arises because the OnNavigationViewSizeChanged method fails to properly reset the layout measurements before arranging the NavigationView. As a result, the NavigationView does not correctly update its layout in response to size changes, causing misalignment or rendering issues in the ScrollView.

Description of Issue Fix

The fix involves updating the OnNavigationViewSizeChanged() method to include a call to InvalidateMeasure() before arranging the NavigationView. This ensures that the layout is accurately recalculated, allowing the ScrollView and other elements within the TabbedPage to be properly measured and arranged during the subsequent layout cycle. This effectively resolves alignment and rendering issues.

Additionally, the Arrange() call is retained within the SizeChanged handler to prevent test failures, specifically avoiding timeout issues observed in the ChangingToNewMauiContextDoesntCrash test. This combination ensures stable layout behavior while resolving the clipping and scrolling issues that occur after window resizing.

Why Tests were not added:

Regarding the test case: The issue only occurs when resizing the window, so it is not possible to add a test case for the window resizing behavior.

Tested the behavior in the following platforms.

  • Windows
  • Mac
  • iOS
  • Android

Issues Fixed

Fixes #26103
Fixes #11402
Fixes #20028

Resaved Test snapshots

Resaved the below-mentioned test snapshot because elements in the TabbedPage were not properly aligned before the fix. The layout changes in OnNavigationViewSizeChanged (adding Arrange() after InvalidateMeasure()) now ensure proper element alignment within the TabbedPage.

  1. DefaultSelectedTabTextColorShouldApplyProperly
  2. FontImageSourceColorShouldApplyOnTabIcon
  3. VerifyTabbedPageMenuItemTextColor
  4. DynamicFontImageSourceColorShouldApplyOnTabIcon
  5. Issue1323Test
  6. TabBarIconsShouldAutoscaleTabbedPage

Output

Before Issue Fix After Issue Fix
BeforeFix-TabbedPage-ScrollView.mp4
AfterFix-TabbedPage-ScrollView.mp4

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Nov 29, 2024
@jsuarezruiz
Copy link
Copy Markdown
Contributor

jsuarezruiz commented Nov 29, 2024

/azp run

@azure-pipelines

This comment was marked as outdated.

@BagavathiPerumal BagavathiPerumal marked this pull request as ready for review November 29, 2024 11:40
@BagavathiPerumal BagavathiPerumal requested a review from a team as a code owner November 29, 2024 11:40
@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

@PureWeen / @jsuarezruiz, We have analysed the test case (Issue1323Test) failure and found that the issue was caused by a button alignment-related issue. Previously, the button inside the page, which was added as a child within the TabbedPage, was not properly aligned in the center.

In this test case, the button was added directly as the content of the page without any additional properties. However, when the page was added as a child page within the TabbedPage, the button was not properly centered.

After the fix, the button inside the page, which was added as a child in the TabbedPage, was properly aligned in the center of the page.

The fix involved calling this.InvalidateMeasure(), which triggered a layout recalculation. This allowed the element within the TabbedPage to be measured and arranged correctly during the subsequent layout cycle.

As a result, the button was properly aligned in the center of the page. Previously, the layout measurements were not recalculated, which caused the button to be misaligned on the page.

Based on the current behavior after the fix, can we resave the current snapshot as the expected snapshot for this test case (Issue1323Test).

Button Alignment in the Page (Output image from the simple sample):

image

Page added as Child in the TabbedPge(Output image from the simple sample):

image

Testcase Image (Before Fix):

image

Current Testcase Image (After Fix):

image

@sheiksyedm sheiksyedm added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Dec 6, 2024
{
if (_navigationView != null)
{
this.InvalidateMeasure();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you remove the call to this.Arrange and leave this.InvalidateMeasure does this all still work?

The call to arrange inside the SizeChanged method here doesn't seem correct.

Also, can you add a test?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PureWeen, I have implemented the suggested changes, tested the fix across all basic scenarios, and also ran UI tests.

Testcase: The test case cannot be created for this scenario as resizing the window to a minimized state is not feasible during testing. Therefore, we have not added a test case for this scenario. Could you suggest alternative ways to address this, since resizing the window to a minimized state isn't possible during testing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to resize the Window or minimize and maximize it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsuarezruiz, The issue occurs only when resizing the window. Could you please share your suggestions on how to resolve it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PureWeen, The Arrange() call in the NavigationView SizeChanged method is necessary to prevent test failures. Without this change, the ChangingToNewMauiContextDoesntCrash test consistently fails with a timeout exception.

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

This comment was marked as off-topic.

1 similar comment
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@Mark-NC001
Copy link
Copy Markdown

@BagavathiPerumal I've tried your pr with my app and it does appear to fix the issue, thanks!

@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

@BagavathiPerumal I've tried your pr with my app and it does appear to fix the issue, thanks!

@Mark-NC001, Thank you so much for taking the time to test the PR with your app. We're truly glad to hear that it resolves the issue.

@jfversluis jfversluis requested a review from PureWeen January 24, 2025 19:27
Copy link
Copy Markdown
Contributor

@jsuarezruiz jsuarezruiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test Issue1323Test related with TabbedPage and Navigation is failing on Windows. Small snapshot differences.
image

{
if (_navigationView != null)
{
this.InvalidateMeasure();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to resize the Window or minimize and maximize it?

@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

The test Issue1323Test related with TabbedPage and Navigation is failing on Windows. Small snapshot differences. image

@jsuarezruiz, It looks expected behavior, as we already mentioned here, can we resave the current snapshot as the expected snapshot for this test case (Issue1323Test).

#26217 (comment)

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

Copy link
Copy Markdown
Contributor

@jsuarezruiz jsuarezruiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be possible to include a test case for this changes?

In Appium, can minimize and maximize the Window (even change the Window size) using:

app.Driver.Manage().Window.Maximize();
app.Driver.Manage().Window.Maximize();

Let me know if can help in someway.

@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

Could be possible to include a test case for this changes?

In Appium, can minimize and maximize the Window (even change the Window size) using:

app.Driver.Manage().Window.Maximize();
app.Driver.Manage().Window.Maximize();

Let me know if can help in someway.

@jsuarezruiz, As suggested, I have tried recreating the test case using Appium but was unable to do so for this scenario. A NotImplementedException occurs when attempting to set the size value using testApp.Driver.Manage().Window.Size.

Exception details:

System.NotImplementedException: Unhandled endpoint: /session/2EDC486C-4A59-4E60-8C80-3EC866B72868/window/rect -- http://127.0.0.1:10100/ with parameters {
wildcards = (
"session/2EDC486C-4A59-4E60-8C80-3EC866B72868/window/rect"
);
}
at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)
at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary2 parameters) at OpenQA.Selenium.WebDriver.InternalExecute(String driverCommandToExecute, Dictionary2 parameters)
at OpenQA.Selenium.Window.set_Size(Size value)
at Microsoft.Maui.TestCases.Tests.Issues.Issue26103.VerifyTabbedPageScrollingBehavior() in /Users/bagavathi/Downloads/maui-fix-26103/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue26103.cs:line 25
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Code:

using Microsoft.Maui.Controls.PlatformConfiguration;
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;
namespace Microsoft.Maui.TestCases.Tests.Issues
{
    public class Issue26103 : _IssuesUITest
    {
        public Issue26103(TestDevice testDevice) : base(testDevice)
        {
        }
        public override string Issue => "TabbedPage - ScrollView not allowing scrolling when it should";
        [Test]
        [Category(UITestCategories.TabbedPage)]
        public void VerifyTabbedPageScrollingBehavior()
        {
            var testApp = (App as AppiumApp);
            if (testApp != null && testApp.Driver != null)
            {
                var originalWindowSize = testApp.Driver.Manage().Window.Size;
                testApp.Driver.Manage().Window.Size = new System.Drawing.Size(100, 200);
                testApp.WaitForElement("stackLayout1");
                VerifyScreenshot();
                testApp.Driver.Manage().Window.Size = originalWindowSize;
            }
        }
    }
}

I also tried creating a test case based on a button click to change the window size, but this approach did not reproduce the issue. The issue only occurs when resizing the window by dragging. Could you please share your suggestions on how to resolve it.

Copy link
Copy Markdown
Contributor

@jsuarezruiz jsuarezruiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some TabbedPage Windows tests failing.

Issue1323Test
Snapshot different than baseline: Issue1323Test.png (0.90% difference)
image
(in red, the differences)

TestPageDoesntCrash

 at UITest.Appium.HelperExtensions.Tap(IUIElement element) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 302
  at UITest.Appium.HelperExtensions.Tap(IApp app, IQuery query) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 38
  at UITest.Appium.HelperExtensions.TapMoreButton(IApp app) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2261
  at Microsoft.Maui.TestCases.Tests.Issues.Issue2809.TestPageDoesntCrash() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue2809.cs:line 19
  at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
  at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Could you review if are related with the changes?

@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

There are some TabbedPage Windows tests failing.

Issue1323Test Snapshot different than baseline: Issue1323Test.png (0.90% difference) image (in red, the differences)

TestPageDoesntCrash

 at UITest.Appium.HelperExtensions.Tap(IUIElement element) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 302
  at UITest.Appium.HelperExtensions.Tap(IApp app, IQuery query) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 38
  at UITest.Appium.HelperExtensions.TapMoreButton(IApp app) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2261
  at Microsoft.Maui.TestCases.Tests.Issues.Issue2809.TestPageDoesntCrash() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue2809.cs:line 19
  at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
  at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Could you review if are related with the changes?

@jsuarezruiz,

Case1: Issue1323Test

It looks expected behavior, as we already mentioned here, can we resave the current snapshot as the expected snapshot for this test case (Issue1323Test).

#26217 (comment)

Case2: TestPageDoesntCrash

I have verified that the test case failures are unrelated to the fix. This has been confirmed on a local machine.

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Mar 19, 2026

/azp run maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review the ai's summary :)

@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

Please review the ai's summary :)

I have reviewed the AI summary. The Arrange() call in the NavigationView.SizeChanged method is necessary to prevent test failures. Without this change, the ChangingToNewMauiContextDoesntCrash test consistently fails with a TimeoutException.

PureWeen pushed a commit that referenced this pull request Mar 23, 2026
#34575)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

Adds Windows platform support to the `maui-copilot` CI pipeline (AzDO
definition 27723), enabling Copilot PR reviews on Windows-targeted PRs.

### Changes

**`eng/pipelines/ci-copilot.yml`**
- Add `catalyst` and `windows` to Platform parameter values
- Add per-platform pool selection (`androidPool`, `iosPool`, `macPool`,
`windowsPool`)
- Skip Xcode, Android SDK, simulator setup for Windows/Catalyst
- Add Windows-specific "Set screen resolution" step (1920x1080)
- Add MacCatalyst-specific "Disable Notification Center" step
- Fix `sed` command for `Directory.Build.Override.props` on Windows (Git
Bash uses GNU sed)
- Handle Copilot CLI PATH detection on Windows vs Unix
- Change `script:` steps to `bash:` for cross-platform consistency

**`.github/scripts/Review-PR.ps1`**
- Add `catalyst` to ValidateSet for Platform parameter

**`.github/scripts/BuildAndRunHostApp.ps1`**
- Add Windows test assembly directory for artifact collection

**`.github/scripts/post-ai-summary-comment.ps1` /
`post-pr-finalize-comment.ps1`**
- Various improvements for cross-platform comment posting

### Validation

Successfully ran the pipeline with `Platform=windows` on multiple
Windows-specific PRs:
- PR #27713 — ✅ Succeeded
- PR #34337 — ✅ Succeeded
- PR #26217, #27609, #27880, #28617, #29927, #30068 — Triggered and
running

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels Apr 5, 2026
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Apr 8, 2026

/rebase

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

🏷️ Test Categories for Regression Detection

No [Category] attributes were found in added test lines, but the changed source file (TabbedPage.Windows.cs) and updated Windows snapshot images indicate TabbedPage is the affected area. Categories were inferred from the source path.

UI Test Categories

Category Source
TabbedPage Inferred from src/Controls/src/Core/TabbedPage/TabbedPage.Windows.cs

Pipeline filter: TabbedPage

Device Test Categories

Category Project Source
TabbedPage Controls Inferred from src/Controls/src/Core/TabbedPage/TabbedPage.Windows.cs

Recommendation: Run device tests: Yes — Windows-specific TabbedPage platform handler code changed.

🚀 Run Targeted Tests on Existing Pipelines

Both maui-pr-uitests and maui-pr-devicetests now support category filtering parameters. To run only the relevant tests for this PR:

UI Tests — trigger maui-pr-uitests with:

Parameter: uiTestCategories = TabbedPage

Device Tests — trigger maui-pr-devicetests with:

Parameter: deviceTestCategories = TabbedPage

When triggered without parameters (e.g., by normal PR push), all categories run as usual.

📁 Changed files (7)

Test/snapshot files (6):

  • src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/DefaultSelectedTabTextColorShouldApplyProperly.png
  • src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/DynamicFontImageSourceColorShouldApplyOnTabIcon.png
  • src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FontImageSourceColorShouldApplyOnTabIcon.png
  • src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/Issue1323Test.png
  • src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/TabBarIconsShouldAutoscaleTabbedPage.png
  • src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyTabbedPageMenuItemTextColor.png

Source files (1):

  • src/Controls/src/Core/TabbedPage/TabbedPage.Windows.cs

ℹ️ Categories are detected from [Category()] attributes in the diff and inferred from changed source file paths.

🏷️ Category detection by Detect Test Categories for Regression Detection

PureWeen and others added 3 commits April 8, 2026 19:58
Backport of dotnet#34801 to main.

The official pack pipeline doesn't need iOS simulators — it only builds
and packs NuGet packages. The simulator install step is timing out on
macOS agents, blocking BAR build production.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Description

Implements the `x:Code` XAML directive, allowing inline C# method
definitions directly in XAML files. This complements the existing XEXPR
(C# Expressions) feature.

Fixes dotnet#34712

## What it does

`x:Code` lets you define methods inline in XAML:

```xml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.MainPage">
    <x:Code><![CDATA[
        void OnButtonClicked(object sender, EventArgs e)
        {
            // inline C# method
        }
    ]]></x:Code>
    <Button Clicked="OnButtonClicked" Text="Click me" />
</ContentPage>
```

## Constraints

- **Requires XSG (XAML Source Generator)** — not supported by Runtime
inflation or XamlC
- **Requires `EnablePreviewFeatures`** — same gate as XEXPR
- **Must be a direct child of the root element** (WPF parity)
- **Must use CDATA** for the code block content
- **Must have `x:Class`** on the root element

## Architecture

x:Code is implemented as a **third source generator pipeline** alongside
CodeBehind (CB) and InitializeComponent (IC):

```
CB → x:Code → IC
```

- `ComputeXCodeSource()` extracts code blocks from parsed XAML
- `XCodeCodeWriter` emits a bare partial class (namespace + class +
verbatim code, no usings)
- The emitted syntax trees feed into the compilation before IC runs
- All IC visitors skip x:Code elements via
`GeneratorHelpers.IsXCodeElement()`

Output hint name format: `{path}_{FileName}.xaml.xcode.cs`

## Diagnostics

| ID | Condition |
|----|-----------|
| MAUIX2012 | `EnablePreviewFeatures` not set (reused from XEXPR) |
| MAUIX2015 | x:Code not a direct child of root element |
| MAUIX2016 | x:Code used without `x:Class` |

## Tests

- **6 SourceGen unit tests** — happy path, multiple blocks, no CDATA,
diagnostics, no-op
- **4 Xaml.UnitTests** — SourceGen success, Runtime failure, XamlC
failure, MockSourceGenerator no-diagnostics

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…otnet#34882)

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details

After tapping CollectionView images to dynamically resize them,
scrolling items off-screen and back causes all images to reset to their
original size.

This is a **failure on the candidate branch**. A PR was previously
created against inflight/candidate:
dotnet#34828. It was closed when the
inflight PR was merged into main. A new PR has now been created
targeting main.

### Regression Details
The regression was introduced by PR dotnet#34534.

### Root Cause

In PR dotnet#34534, TemplatedItemViewHolder.Recycle() set View = null and
_selectedTemplate = null, which forced Bind() to recreate the view from
the DataTemplate on every scroll recycle. Since the template defines
HeightRequest = 60, any runtime size changes made by the user were lost.

### Description of Change

- Recycle(): Removed View = null and _selectedTemplate = null. Now only
_itemContentView.Recycle() is called, which disconnects the native
handler while preserving the MAUI view reference.

- Bind(): Added a View?.Handler is null check within the existing if
(!templateChanging) block. When the handler has been disconnected during
recycle and the template has not changed, PropagatePropertyChanged and
RealizeContent(View, itemsView) are invoked to reconnect the native
handler to the existing MAUI view, preserving runtime property changes
without recreating the view.

### Issues Fixed
Fixes dotnet#34783

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/0befe25b-8467-4de7-a5da-926b61d783a3">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/6b3368a4-ea7c-4124-8a68-d8dc0bb3c2b9">
|
@dotnet dotnet deleted a comment from MauiBot Apr 12, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 12, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 12, 2026

🚦 Gate — Test Before and After Fix

👋 @BagavathiPerumal — new gate results are available. Please review the latest session below.

🚦 Gate Session713f1e8 · fix-26108-Made code changes to bypass the extension method guard and Inline code comments have been removed to align with the repository style. · 2026-04-13 11:50 UTC

Gate Result: ⚠️ SKIPPED

No tests were detected in this PR.

Recommendation: Add tests to verify the fix using the write-tests-agent:

@copilot write tests for this PR

The agent will analyze the issue, determine the appropriate test type (UI test, device test, unit test, or XAML test), and create tests that verify the fix.



🚦 Gate Session4eb69f6 · fix-26103-Resaved the test image. · 2026-04-12 15:13 UTC

Gate Result: ⚠️ SKIPPED

No tests were detected in this PR.

Recommendation: Add tests to verify the fix using the write-tests-agent:

@copilot write tests for this PR

The agent will analyze the issue, determine the appropriate test type (UI test, device test, unit test, or XAML test), and create tests that verify the fix.


@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 12, 2026

🤖 AI Summary

👋 @BagavathiPerumal — new AI review results are available. Please review the latest session below.

📊 Review Session713f1e8 · fix-26108-Made code changes to bypass the extension method guard and Inline code comments have been removed to align with the repository style. · 2026-04-13 13:22 UTC
🔍 Pre-Flight — Context & Validation

Issue: #26103 - TabbedPage - ScrollView not allowing scrolling when it should
Related Issues: #11402 - TabbedPage resize hides bottom content (Windows); #20028 - Grid overflows child ContentPage of TabbedPage on resize (Windows)
PR: #26217 - [Windows] TabbedPage: Refresh layout when NavigationView size changes
Author: BagavathiPerumal (community/Syncfusion partner)
Platforms Affected: Windows (all issues are Windows-only)
Files Changed: 1 implementation, 6 snapshots (no new tests)

Key Findings

  • Root cause: OnNavigationViewSizeChanged called this.Arrange(_navigationView) which uses _navigationView.ActualWidth/Height with a "no-op if unchanged" guard. Layout was not being invalidated before arrange, causing stale measure values and incorrect layout after window resize.
  • Fix: Adds this.InvalidateMeasure() before Arrange(), and switches from this.Arrange(_navigationView) to this.Arrange(new Rect(0, 0, e.NewSize.Width, e.NewSize.Height)).
  • Unresolved PureWeen concern: "The call to arrange inside the SizeChanged method here doesn't seem correct. If you remove the call to this.Arrange and leave this.InvalidateMeasure does this all still work?"
  • Author says Arrange() is needed to prevent ChangingToNewMauiContextDoesntCrash device test from timing out.
  • 6 Windows snapshot files were regenerated because the fix corrects layout alignment in TabbedPage.
  • Gate: ⚠️ SKIPPED — no tests detected in this PR (no new test files; window resize can't be automated per author).
  • Prior agent review: ⚠️ REQUEST CHANGES (same key concerns remain)

Edge Cases

  • this.Arrange(new Rect(0,0, e.NewSize.Width, e.NewSize.Height)) arranges TabbedPage with the _navigationView's new size — not the window size. In the FlyoutPage-embedded scenario, NavigationView IS the TabbedPage's root, so sizes match.
  • Old code had a guard (if (!view.Frame.Equals(rect)) view.Arrange(rect)) preventing redundant arrange calls. New code always arranges unconditionally — potential performance/recursion risk.
  • SizeChanged is subscribed only in SetupNavigationView() when _navigationView.TopNavArea == null (template not yet applied). The handler is unsubscribed in OnHandlerDisconnected. So it fires only briefly during initial setup.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #26217 Add InvalidateMeasure() before Arrange(), use e.NewSize directly ⏳ PENDING TabbedPage.Windows.cs + 6 snapshots Original PR

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (opus-4.6) InvalidateMeasure() alone — no Arrange() ✅ PASS (59/59) TabbedPage.Windows.cs Simplest; directly addresses PureWeen's concern
2 try-fix (sonnet-4.6) Unsubscribe SizeChanged after OnApplyTemplateFinished; trust layout pipeline ✅ PASS (59/59) TabbedPage.Windows.cs Addresses lifecycle bug but may not fix actual window-resize scenario
3 try-fix (gpt-5.3-codex) Remove frame-equality guard in FrameworkElementExtensions.Arrange globally ❌ FAIL (53/59) FrameworkElementExtensions.cs Too broad — caused visual regressions in 6 snapshot tests
4 try-fix (gpt-5.4) ForceLayout() in OnNavigationViewSizeChanged ✅ PASS (59/59) TabbedPage.Windows.cs ForceLayout() is a legacy/deprecated API path
PR PR #26217 InvalidateMeasure() + Arrange(new Rect(0,0,w,h)) ⏳ Gate skipped TabbedPage.Windows.cs + 6 snapshots Original PR; has unresolved reviewer concern

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 NO NEW IDEAS Design space exhausted; noted possible combination of Attempt 1 + 2

Exhausted: Yes
Selected Fix: Attempt 1 — InvalidateMeasure() alone

Reason: Simplest passing alternative. Directly addresses PureWeen's concern. InvalidateMeasure() triggers the layout system to re-measure and re-arrange naturally — no questionable Arrange() in a SizeChanged handler. Passes all 59 TabbedPage tests. The PR should be updated to remove the Arrange() call.

Note on Attempt 2: While it passed tests, it unsubscribes the SizeChanged handler after initialization — which may mean actual runtime window-resize events are not handled. Snapshot tests only test static layout. Attempt 1 is safer as it keeps the handler for real resizes.


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE 3 linked issues (#26103, #11402, #20028); Windows-only layout bug
Gate ⚠️ SKIPPED No tests detected in PR (window resize not automatable per author)
Try-Fix ✅ COMPLETE 4 attempts; 3 passing, 1 failing
Report ✅ COMPLETE

Summary

This PR fixes a long-standing Windows TabbedPage layout bug where resizing the window causes incorrect layout measurements (ScrollView can't scroll, content clipped, Grid overflows). The core fix is in OnNavigationViewSizeChanged in TabbedPage.Windows.cs. The fix is directionally correct, but an alternative approach found by exploration is simpler and directly addresses the main unresolved reviewer concern.

Root Cause

OnNavigationViewSizeChanged called this.Arrange(_navigationView) via FrameworkElementExtensions.Arrange(IView, FrameworkElement), which:

  1. Uses stale ActualWidth/Height values (not yet updated at the time of the event)
  2. Has a "no-op if unchanged" guard — silently skips the arrange if view.Frame already equals the stale rect

The result: layout measurements are never invalidated before the next arrange pass, so child views (ScrollView, Grid) render with the old dimensions.

Fix Quality

PR's approach: Adds this.InvalidateMeasure() before changing this.Arrange(_navigationView) to this.Arrange(new Rect(0, 0, e.NewSize.Width, e.NewSize.Height)).

Concerns with PR's fix:

  1. Unresolved reviewer concern (PureWeen): "The call to arrange inside the SizeChanged method here doesn't seem correct. If you remove the call to this.Arrange and leave this.InvalidateMeasure does this all still work?" — this thread is still open.
  2. Try-Fix confirms PureWeen is right: Attempt 1 (InvalidateMeasure() alone, no Arrange()) passes all 59 TabbedPage tests. The explicit Arrange(new Rect(...)) in a SizeChanged handler is unnecessary.
  3. Unconditional Arrange: The PR removes the "only if changed" guard, so Arrange is called on every resize even if size hasn't changed — minor performance concern.
  4. 6 snapshot files updated — expected, since the layout fix changes how the TabbedPage renders. The updates appear visually correct.
  5. No new tests — Gate was skipped. The author reasonably argues window resize can't be automated.

Recommended Change

The PR should be simplified to:

void OnNavigationViewSizeChanged(object sender, SizeChangedEventArgs e)
{
    if (_navigationView != null)
        this.InvalidateMeasure();
}

This is the minimal fix that:

  • Directly addresses PureWeen's concern
  • Removes the questionable Arrange() call from a SizeChanged handler
  • Passes all 59 TabbedPage UI tests (verified empirically)
  • Trusts WinUI's layout system to handle re-arrangement after measure invalidation

Try-Fix Comparison

See try-fix/content.md for full table. Summary: InvalidateMeasure() alone (Attempt 1) is the best alternative — simpler, equally effective, answers the open reviewer question.

Selected Fix: Attempt 1 (not PR's fix)



📊 Review Session4eb69f6 · fix-26103-Resaved the test image. · 2026-04-12 15:56 UTC
🔍 Pre-Flight — Context & Validation

Issue: #26103 - TabbedPage - ScrollView not allowing scrolling when it should
Related Issues: #11402 - TabbedPage app on resize hides page bottom content; #20028 - TabbedPage layout misalignment on window resize
PR: #26217 - [Windows] TabbedPage: Refresh layout when NavigationView size changes
Platforms Affected: Windows (fix), snapshot updates affect Windows UI tests
Files Changed: 1 implementation, 6 test snapshots (no new tests added)
Gate Result: ⚠️ SKIPPED — no tests detected

Key Findings

  • Root cause: OnNavigationViewSizeChanged only called this.Arrange(_navigationView) without first invalidating the measure cache, so the layout pass used stale measurements after a window resize, causing scroll content to be clipped.
  • Fix: The PR adds this.InvalidateMeasure() before the existing this.Arrange(_navigationView) call inside the null-guard block.
  • Concern from reviewer (PureWeen): Asked whether Arrange() is even needed and whether InvalidateMeasure() alone suffices. The PR author claims removing Arrange() causes the ChangingToNewMauiContextDoesntCrash test to time out. This claim has not been independently verified.
  • Comment from inline reviewer (jsuarezruiz): Suggested adding a test using Appium Window.Maximize()/Window.Minimize() to reproduce. Author attempted but could not successfully reproduce via Appium test.
  • Reporter confirmed fix works: Issue reporter (Mark-NC001) tested PR and confirmed ScrollView now scrolls to the bottom correctly.
  • No new tests added: PR author argues window resize is not automatable. Gate skipped since no tests present.
  • Snapshot changes: 6 TabbedPage Windows snapshot baselines were updated because the layout is now more correct (items better aligned). This is an expected side-effect of the fix.
  • Inline comments: One unresolved review thread — PureWeen's question about whether Arrange() is still needed.
  • Prior agent reviews: None (only an AI summary posted by the PR author, not an agent review).

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #26217 Add InvalidateMeasure() before existing Arrange(_navigationView) call in OnNavigationViewSizeChanged ⚠️ SKIPPED (no tests) TabbedPage.Windows.cs + 6 snapshots Original PR; Arrange() kept to prevent test timeout per author

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Replace this.Arrange(_navigationView) with _navigationView.InvalidateMeasure() to let WinUI's layout cycle handle re-arrangement ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly, unit tests pass; device tests unavailable
2 try-fix (claude-sonnet-4.6) Directly measure+arrange _displayedPage using _navigationFrame.ActualWidth/Height (content area dimensions) ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly; device tests unavailable
3 try-fix (gpt-5.3-codex) Dual invalidation (InvalidateMeasure + InvalidateArrange) on both this and _navigationView, no explicit Arrange() ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly; device tests unavailable
4 try-fix (gpt-5.4) _displayedPage.InvalidateMeasure() + platform view fallback invalidation ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly; device tests unavailable
PR PR #26217 Add this.InvalidateMeasure() before existing this.Arrange(_navigationView) call in OnNavigationViewSizeChanged ⚠️ SKIPPED (Gate) TabbedPage.Windows.cs + 6 snapshots Original PR

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes Key insight: this.Arrange(_navigationView) uses FrameworkElementExtensions.Arrange (line 184) which has a guard: if (!view.Frame.Equals(rect)). This means if MAUI Frame already matches the current NavigationView dimensions, the arrange is silently skipped. New ideas: (1) Bypass guard with e.NewSize directly calling VisualElement.Arrange(Rect) unconditionally; (2) Defer layout to next dispatcher tick via DispatcherQueue.TryEnqueue; (3) Subscribe to _navigationFrame.SizeChanged instead; (4) Use WinUI _navigationView.UpdateLayout()

Exhausted: Yes — all 4 models + cross-pollination completed

Key Infrastructure Finding: All Windows device tests (including ChangingToNewMauiContextDoesntCrash) blocked with WindowsAppSDKSelfContained requires a supported Windows architecture. Unit tests pass for all approaches.

Selected Fix: PR #26217 — No attempt could be validated over the PR's fix due to device test infrastructure unavailability. The PR's approach (InvalidateMeasure() + Arrange()) is the most tested fix (reporter confirmed working). However, PureWeen's concern about the Arrange() call inside SizeChanged remains unresolved. The cross-pollination insight about the FrameworkElementExtensions.Arrange guard (line 184) is relevant — if the guard is the real root cause, bypassing it with e.NewSize might be cleaner.


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #26103 (Windows TabbedPage ScrollView clipping on resize) + related #11402, #20028
Gate ⚠️ SKIPPED No tests detected in PR
Try-Fix ⚠️ BLOCKED 4 attempts, 0 passing — Windows device test infrastructure unavailable (WindowsAppSDKSelfContained requires a supported Windows architecture)
Report ✅ COMPLETE

Selected Fix: PR (no alternative could be validated)


Summary

PR #26217 fixes a Windows-only layout bug where TabbedPage containing a ScrollView fails to correctly update its layout after window resize. The fix adds this.InvalidateMeasure() before the existing this.Arrange(_navigationView) call in OnNavigationViewSizeChanged. This is a 5-line change to TabbedPage.Windows.cs plus 6 updated snapshot baselines.

The fix is confirmed working by the issue reporter. However, there is an unresolved reviewer concern from PureWeen about whether the Arrange() call inside SizeChanged is necessary and correct, and no new automated tests were added.


Root Cause

When the window is resized, the WinUI NavigationView.SizeChanged event fires. The original handler called this.Arrange(_navigationView), which uses the FrameworkElementExtensions.Arrange(IView, FrameworkElement) extension method (defined in FrameworkElementExtensions.cs:184). This extension method:

  1. Builds a Rect(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight) from current NavigationView dimensions
  2. Only calls view.Arrange(rect) if !view.Frame.Equals(rect) (guard to prevent redundant arranges)

The bug: view.Arrange(rect) does NOT call InvalidateMeasure() first. So when the layout pass runs, the MAUI measure cache still contains stale sizes from before the resize. The ScrollView child's DesiredSize is never re-measured with the new window dimensions, causing clipping.

The PR's fix correctly adds this.InvalidateMeasure() before this.Arrange() so that stale measurements are discarded before the arrangement pass runs.


Fix Quality

Strengths:

  • ✅ Fix is minimal and targeted (5 lines changed in one method)
  • ✅ Addresses the correct root cause (stale measure cache)
  • ✅ Confirmed working by issue reporter (Mark-NC001)
  • ✅ Snapshot updates are expected and correct (layout is now more accurate)

Concerns requiring author response:

  1. ❓ Is this.Arrange(_navigationView) still needed? — PureWeen asked whether InvalidateMeasure() alone suffices. The PR author claims removing Arrange() causes ChangingToNewMauiContextDoesntCrash device test to time out. This claim should be independently verified. Calling Arrange() inside a SizeChanged handler of the same view is architecturally unusual and could cause layout re-entrancy issues.

  2. 🔍 Consider bypassing the extension method guard — The FrameworkElementExtensions.Arrange extension has a frame-equality guard. If the new size matches the MAUI Frame (e.g., when window is restored to its original size), the arrange is silently skipped. A more robust approach may be: this.InvalidateMeasure(); this.Arrange(new Graphics.Rect(0, 0, e.NewSize.Width, e.NewSize.Height)); using e.NewSize from the event args to bypass the guard unconditionally.

  3. ⚠️ No new tests — The Gate was skipped because no tests were added. The reviewer (jsuarezruiz) suggested using Appium's app.Driver.Manage().Window.Maximize() / Minimize() to test window resize behavior. This is technically feasible and should be explored.

  4. 🧹 Inline code comments — The two inline comments added (// Ensure TabbedPage layout responds to NavigationView size changes, // Complete layout to fix frame dimensions) do not add significant clarity over the code itself and should follow the repo convention of minimal comments.


Recommendation Details

The fix is functionally correct based on reporter confirmation and code analysis. However, the open reviewer question about Arrange() necessity plus the absence of tests leads to a REQUEST CHANGES recommendation. The author should:

  1. Address PureWeen's concern about Arrange() vs InvalidateMeasure() alone with a reproducible test or CI evidence
  2. Consider using e.NewSize to bypass the extension guard for robustness
  3. Explore adding a window-resize UI test as jsuarezruiz suggested
  4. Remove or simplify the inline code comments to match repo style

…Inline code comments have been removed to align with the repository style.
@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

BagavathiPerumal commented Apr 13, 2026

🤖 AI Summary

👋 @BagavathiPerumal — new AI review results are available. Please review the latest session below.

📊 Review Session4eb69f6 · fix-26103-Resaved the test image. · 2026-04-12 15:56 UTC
🔍 Pre-Flight — Context & Validation
Issue: #26103 - TabbedPage - ScrollView not allowing scrolling when it should Related Issues: #11402 - TabbedPage app on resize hides page bottom content; #20028 - TabbedPage layout misalignment on window resize PR: #26217 - [Windows] TabbedPage: Refresh layout when NavigationView size changes Platforms Affected: Windows (fix), snapshot updates affect Windows UI tests Files Changed: 1 implementation, 6 test snapshots (no new tests added) Gate Result: ⚠️ SKIPPED — no tests detected

Key Findings

  • Root cause: OnNavigationViewSizeChanged only called this.Arrange(_navigationView) without first invalidating the measure cache, so the layout pass used stale measurements after a window resize, causing scroll content to be clipped.
  • Fix: The PR adds this.InvalidateMeasure() before the existing this.Arrange(_navigationView) call inside the null-guard block.
  • Concern from reviewer (PureWeen): Asked whether Arrange() is even needed and whether InvalidateMeasure() alone suffices. The PR author claims removing Arrange() causes the ChangingToNewMauiContextDoesntCrash test to time out. This claim has not been independently verified.
  • Comment from inline reviewer (jsuarezruiz): Suggested adding a test using Appium Window.Maximize()/Window.Minimize() to reproduce. Author attempted but could not successfully reproduce via Appium test.
  • Reporter confirmed fix works: Issue reporter (Mark-NC001) tested PR and confirmed ScrollView now scrolls to the bottom correctly.
  • No new tests added: PR author argues window resize is not automatable. Gate skipped since no tests present.
  • Snapshot changes: 6 TabbedPage Windows snapshot baselines were updated because the layout is now more correct (items better aligned). This is an expected side-effect of the fix.
  • Inline comments: One unresolved review thread — PureWeen's question about whether Arrange() is still needed.
  • Prior agent reviews: None (only an AI summary posted by the PR author, not an agent review).

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #26217 Add InvalidateMeasure() before existing Arrange(_navigationView) call in OnNavigationViewSizeChanged ⚠️ SKIPPED (no tests) TabbedPage.Windows.cs + 6 snapshots Original PR; Arrange() kept to prevent test timeout per author
🔧 Fix — Analysis & Comparison

Fix Candidates

Source Approach Test Result Files Changed Notes

1 try-fix (claude-opus-4.6) Replace this.Arrange(_navigationView) with _navigationView.InvalidateMeasure() to let WinUI's layout cycle handle re-arrangement ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly, unit tests pass; device tests unavailable
2 try-fix (claude-sonnet-4.6) Directly measure+arrange _displayedPage using _navigationFrame.ActualWidth/Height (content area dimensions) ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly; device tests unavailable
3 try-fix (gpt-5.3-codex) Dual invalidation (InvalidateMeasure + InvalidateArrange) on both this and _navigationView, no explicit Arrange() ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly; device tests unavailable
4 try-fix (gpt-5.4) _displayedPage.InvalidateMeasure() + platform view fallback invalidation ⚠️ BLOCKED TabbedPage.Windows.cs Compiles cleanly; device tests unavailable
PR PR #26217 Add this.InvalidateMeasure() before existing this.Arrange(_navigationView) call in OnNavigationViewSizeChanged ⚠️ SKIPPED (Gate) TabbedPage.Windows.cs + 6 snapshots Original PR

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes Key insight: this.Arrange(_navigationView) uses FrameworkElementExtensions.Arrange (line 184) which has a guard: if (!view.Frame.Equals(rect)). This means if MAUI Frame already matches the current NavigationView dimensions, the arrange is silently skipped. New ideas: (1) Bypass guard with e.NewSize directly calling VisualElement.Arrange(Rect) unconditionally; (2) Defer layout to next dispatcher tick via DispatcherQueue.TryEnqueue; (3) Subscribe to _navigationFrame.SizeChanged instead; (4) Use WinUI _navigationView.UpdateLayout()
Exhausted: Yes — all 4 models + cross-pollination completed

Key Infrastructure Finding: All Windows device tests (including ChangingToNewMauiContextDoesntCrash) blocked with WindowsAppSDKSelfContained requires a supported Windows architecture. Unit tests pass for all approaches.

Selected Fix: PR #26217 — No attempt could be validated over the PR's fix due to device test infrastructure unavailability. The PR's approach (InvalidateMeasure() + Arrange()) is the most tested fix (reporter confirmed working). However, PureWeen's concern about the Arrange() call inside SizeChanged remains unresolved. The cross-pollination insight about the FrameworkElementExtensions.Arrange guard (line 184) is relevant — if the guard is the real root cause, bypassing it with e.NewSize might be cleaner.

📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #26103 (Windows TabbedPage ScrollView clipping on resize) + related #11402, #20028
Gate ⚠️ SKIPPED No tests detected in PR
Try-Fix ⚠️ BLOCKED 4 attempts, 0 passing — Windows device test infrastructure unavailable (WindowsAppSDKSelfContained requires a supported Windows architecture)
Report ✅ COMPLETE
Selected Fix: PR (no alternative could be validated)

Summary

PR #26217 fixes a Windows-only layout bug where TabbedPage containing a ScrollView fails to correctly update its layout after window resize. The fix adds this.InvalidateMeasure() before the existing this.Arrange(_navigationView) call in OnNavigationViewSizeChanged. This is a 5-line change to TabbedPage.Windows.cs plus 6 updated snapshot baselines.

The fix is confirmed working by the issue reporter. However, there is an unresolved reviewer concern from PureWeen about whether the Arrange() call inside SizeChanged is necessary and correct, and no new automated tests were added.

Root Cause

When the window is resized, the WinUI NavigationView.SizeChanged event fires. The original handler called this.Arrange(_navigationView), which uses the FrameworkElementExtensions.Arrange(IView, FrameworkElement) extension method (defined in FrameworkElementExtensions.cs:184). This extension method:

  1. Builds a Rect(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight) from current NavigationView dimensions
  2. Only calls view.Arrange(rect) if !view.Frame.Equals(rect) (guard to prevent redundant arranges)

The bug: view.Arrange(rect) does NOT call InvalidateMeasure() first. So when the layout pass runs, the MAUI measure cache still contains stale sizes from before the resize. The ScrollView child's DesiredSize is never re-measured with the new window dimensions, causing clipping.

The PR's fix correctly adds this.InvalidateMeasure() before this.Arrange() so that stale measurements are discarded before the arrangement pass runs.

Fix Quality

Strengths:

  • ✅ Fix is minimal and targeted (5 lines changed in one method)
  • ✅ Addresses the correct root cause (stale measure cache)
  • ✅ Confirmed working by issue reporter (Mark-NC001)
  • ✅ Snapshot updates are expected and correct (layout is now more accurate)

Concerns requiring author response:

  1. ❓ Is this.Arrange(_navigationView) still needed? — PureWeen asked whether InvalidateMeasure() alone suffices. The PR author claims removing Arrange() causes ChangingToNewMauiContextDoesntCrash device test to time out. This claim should be independently verified. Calling Arrange() inside a SizeChanged handler of the same view is architecturally unusual and could cause layout re-entrancy issues.
  2. 🔍 Consider bypassing the extension method guard — The FrameworkElementExtensions.Arrange extension has a frame-equality guard. If the new size matches the MAUI Frame (e.g., when window is restored to its original size), the arrange is silently skipped. A more robust approach may be: this.InvalidateMeasure(); this.Arrange(new Graphics.Rect(0, 0, e.NewSize.Width, e.NewSize.Height)); using e.NewSize from the event args to bypass the guard unconditionally.
  3. ⚠️ No new tests — The Gate was skipped because no tests were added. The reviewer (jsuarezruiz) suggested using Appium's app.Driver.Manage().Window.Maximize() / Minimize() to test window resize behavior. This is technically feasible and should be explored.
  4. 🧹 Inline code comments — The two inline comments added (// Ensure TabbedPage layout responds to NavigationView size changes, // Complete layout to fix frame dimensions) do not add significant clarity over the code itself and should follow the repo convention of minimal comments.

Recommendation Details

The fix is functionally correct based on reporter confirmation and code analysis. However, the open reviewer question about Arrange() necessity plus the absence of tests leads to a REQUEST CHANGES recommendation. The author should:

  1. Address PureWeen's concern about Arrange() vs InvalidateMeasure() alone with a reproducible test or CI evidence
  2. Consider using e.NewSize to bypass the extension guard for robustness
  3. Explore adding a window-resize UI test as jsuarezruiz suggested
  4. Remove or simplify the inline code comments to match repo style

I’ve reviewed and updated the changes based on the latest findings. Specifically:

  • The reason for using Arrange(_navigationView) has already been updated in the comment. It is currently required to prevent failures in ChangingToNewMauiContextDoesntCrash.
  • The code has been updated based on the suggestion to bypass the extension method guard.
  • The reason for not adding a test case for this fix has already been mentioned in the PR template and also clarified in the comments.
  • Inline code comments have been removed to align with the repository style.

@kubaflo kubaflo changed the base branch from main to inflight/current April 13, 2026 17:36
@kubaflo kubaflo merged commit 1b98873 into dotnet:inflight/current Apr 13, 2026
26 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-tabbedpage TabbedPage community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet